package com.ppch.wuwamanus.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ppch.wuwamanus.exception.ErrorCode;
import com.ppch.wuwamanus.exception.ThrowUtils;
import com.ppch.wuwamanus.model.dto.chat_history.ChatHistoryQueryRequest;
import com.ppch.wuwamanus.model.entity.ChatHistory;
import com.ppch.wuwamanus.model.entity.User;
import com.ppch.wuwamanus.model.enums.ChatHistoryMessageTypeEnum;
import com.ppch.wuwamanus.service.ChatHistoryService;
import com.ppch.wuwamanus.mapper.ChatHistoryMapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
* @author 鲸落
* @description 针对表【chat_history(对话历史)】的数据库操作Service实现
* @createDate 2025-08-18 15:52:58
*/
@Service
public class ChatHistoryServiceImpl extends ServiceImpl<ChatHistoryMapper, ChatHistory>
    implements ChatHistoryService{

    @Resource
    private ChatHistoryMapper chatHistoryMapper;

    /**
     * 增加对话历史记录
     * @param chatId 对话ID
     * @param message 对话内容
     * @param messageType 对话类型
     * @param userId 对话用户ID
     * @return 是否成功
     */
    @Override
    public boolean addChatHistory(Long chatId, String message, String messageType, Long userId) {
        //1.基础校验
        ThrowUtils.throwIf(chatId == null || chatId <= 0, ErrorCode.PARAMS_ERROR, "应用ID不能为空");
        ThrowUtils.throwIf(StrUtil.isBlank(message), ErrorCode.PARAMS_ERROR, "消息内容不能为空");
        ThrowUtils.throwIf(StrUtil.isBlank(messageType), ErrorCode.PARAMS_ERROR, "消息类型不能为空");
        ThrowUtils.throwIf(userId == null || userId <= 0, ErrorCode.PARAMS_ERROR, "用户ID不能为空");
        //2.验证消息类型是否有效
        ChatHistoryMessageTypeEnum messageTypeEnum = ChatHistoryMessageTypeEnum.getEnumByValue(messageType);
        ThrowUtils.throwIf(messageTypeEnum == null, ErrorCode.PARAMS_ERROR, "不支持的消息类型: " + messageType);
        //3.插入对话记录
        ChatHistory chatHistory = ChatHistory.builder()
                .chatId(chatId)
                .message(message)
                .messageType(messageType)
                .userId(userId)
                .build();
        return this.save(chatHistory);
    }


    /**
     * 根据对话ID删除对话历史记录
     * @param chatId 对话ID
     * @return 是否成功
     */
    @Override
    public boolean deleteChatHistoryByChatId(Long chatId) {
        //1.基础校验
        ThrowUtils.throwIf(chatId == null || chatId <= 0, ErrorCode.PARAMS_ERROR, "应用ID不能为空");
        //2.删除对话历史记录
        QueryWrapper<ChatHistory> chatHistoryQueryWrapper = new QueryWrapper<>();
        chatHistoryQueryWrapper.eq("chatId", chatId);
        return this.remove(chatHistoryQueryWrapper);
    }


    /**
     * 分页查询对话历史记录
     *
     * @param chatId         对话ID
     * @param pageSize       每页大小
     * @param lastCreateTime 最后创建时间
     * @param loginUser      登录用户
     * @return 对话历史记录分页结果
     */
    @Override
    public Page listChatHistoryByPage(Long chatId, int pageSize, LocalDateTime lastCreateTime, User loginUser) {
        ThrowUtils.throwIf(chatId == null || chatId <= 0, ErrorCode.PARAMS_ERROR, "应用ID不能为空");
        ThrowUtils.throwIf(pageSize <= 0 || pageSize > 50, ErrorCode.PARAMS_ERROR, "页面大小必须在1-50之间");
        ThrowUtils.throwIf(loginUser == null, ErrorCode.NOT_LOGIN_ERROR);
        // 构建查询条件
        ChatHistoryQueryRequest queryRequest = new ChatHistoryQueryRequest();
        queryRequest.setUserId(loginUser.getId());
        queryRequest.setPageSize(pageSize);
        queryRequest.setChatId(chatId);
        queryRequest.setLastCreateTime(lastCreateTime);
        LambdaQueryWrapper queryWrapper = this.getQueryWrapper(queryRequest);
        // 查询数据
        Page page = this.page(Page.of(1, pageSize), queryWrapper);
        return page;
    }

    /**
     * 获取查询包装类
     *
     * @param chatHistoryQueryRequest 对话历史查询请求
     * @return LambdaQueryWrapper
     */
    @Override
    public LambdaQueryWrapper<ChatHistory> getQueryWrapper(ChatHistoryQueryRequest chatHistoryQueryRequest) {
        LambdaQueryWrapper<ChatHistory> queryWrapper = new LambdaQueryWrapper<>();
        if (chatHistoryQueryRequest == null) {
            return queryWrapper;
        }
        Long id = chatHistoryQueryRequest.getId();
        String message = chatHistoryQueryRequest.getMessage();
        String messageType = chatHistoryQueryRequest.getMessageType();
        Long chatId = chatHistoryQueryRequest.getChatId();
        Long userId = chatHistoryQueryRequest.getUserId();
        //最后一条对话历史记录的创建时间
        LocalDateTime lastCreateTime = chatHistoryQueryRequest.getLastCreateTime();
        // 拼接基础查询条件
        queryWrapper.eq(ObjectUtil.isNotEmpty(id), ChatHistory::getId, id)
                .eq(StrUtil.isNotBlank(message), ChatHistory::getMessage, message)
                .eq(StrUtil.isNotBlank(messageType), ChatHistory::getMessageType, messageType)
                .eq(ObjectUtil.isNotEmpty(chatId), ChatHistory::getChatId, chatId)
                .eq(ObjectUtil.isNotEmpty(userId), ChatHistory::getUserId, userId)
                // 游标查询逻辑 - 只使用 createTime 作为游标，查询创建时间 < lastCreateTime 的对话历史记录
                .lt(ObjectUtil.isNotEmpty(lastCreateTime), ChatHistory::getCreateTime, lastCreateTime);
        //TODO：使用子查询和窗口函数去除 message 和 messageType 都相同的重复数据
//        String subSql = "SELECT * FROM (" +
//                "SELECT *, ROW_NUMBER() OVER (PARTITION BY message, messageType ORDER BY createTime DESC) as rn " +
//                "FROM chat_history" +
//                ") t WHERE rn = 1";
//        queryWrapper.apply("id IN (SELECT id FROM (" + subSql + ") AS temp)");

        // 默认按创建时间降序
        queryWrapper.orderByDesc(ChatHistory::getCreateTime);

        return queryWrapper;
    }



    /**
     * 根据用户 ID 获取用户所有对话历史，并按对话 ID 分组返回每组最早的消息，消息按照创建时间降序排序（8.29 -> 8.27 -> 8.11）
     * @param userId 用户 ID
     * @return 按对话ID分组的 earliest 消息映射表
     */
    @Override
    public Map<Long, List<ChatHistory>> getEarliestMessageByConversation(Long userId) {
        // 1. 查询用户所有对话历史（按对话ID和创建时间升序排列）
        LambdaQueryWrapper<ChatHistory> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ChatHistory::getUserId, userId)
                .orderByAsc(ChatHistory::getCreateTime);

        List<ChatHistory> chatHistoryList = chatHistoryMapper.selectList(queryWrapper);

        // 2. 按chatId分组并取每组最早的消息
        Map<Long, List<ChatHistory>> earliestMessages = chatHistoryList.stream()
                .collect(Collectors.groupingBy(
                        ChatHistory::getChatId,
                        Collectors.collectingAndThen(
                                Collectors.toList(),
                                list -> Collections.singletonList(list.get(0)) // 获取最早的消息并包装成列表
                        )
                ));

        // 3. 将结果按照创建时间降序排序
        return earliestMessages.entrySet().stream()
                .sorted((entry1, entry2) ->
                        entry2.getValue().get(0).getCreateTime()
                                .compareTo(entry1.getValue().get(0).getCreateTime())
                )
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        Map.Entry::getValue,
                        (e1, e2) -> e1,
                        LinkedHashMap::new
                ));
    }

}




